Universo Online
Web Sites Pessoais
Anterior Próximo Índice

Chamando uma Rotina Distante em Assembly a partir do Turbo Pascal.

A direferença entre uma rotina próxima e uma rotina distante é que nessa última o processador Intel salva o valor de CS e IP na pilha. Isso significa que para acessar um parâmetro devemos adicionar dois bytes a mais em BP já que há dois bytes extras na pilha (lembre-se: a pilha armazena palavras, que são dois bytes para o modo 8086 do processador, também chamado de Modo Real). Em modelos grandes de memória, uma rotina distante pode ser chamada de outro segmento diferente do da rotina chamadora. A rotina distante deve terminar com um RETF (far return) para atualizar CS:IP com o endereço de retorno. O deslocamento de cada parâmetro na pilha, em relação ao endereço base , que é dado por SS, devem ser esses:

SP      =  Valor Inicial de SP
SP - 02 = Valor de SP após empilhar o primeiro parâmetro
SP - 04 = Valor de SP após empilhar o segundo parâmetro
SP - 06 = Valor de SP após empilhar o terceiro parâmetro
SP - 08 = Valor de SP após a chamada da rotina empilhar o valor de CS
SP - 10 = Valor de SP após a rotina empilhar o valor IP
SP - 12 = Valor de SP após empilhar o valor de BP
Para acessar cada parâmetro você deve considerar a seguinte aritmética:

Endereço do primeiro parâmetro em relação a SS = [BP + 10] = [(SP - 12) + 10] = [SP - 2]

Endereço do segundo parâmetro em relação a SS= [BP + 08] = [(SP - 12) + 08] = [SP - 4]

Endereço do terceiro parâmetro em relação a SS = [BP + 06] = [(SP - 12) + 06] = [SP - 6]

E como você pode constantar acima, o resultado confere com os deslocamentos esperados para cada parâmetro na pilha.

;PROCF.ASM
;DEMONSTRACAO DE UMA ROTINA COM 3 PARAMETROS
;CHAMAR DE PROGRAMA EM TURBO PASCAL
;PARA MONTAR DIGITE: nasm -fobj procf.asm


segment CODE class=CODE align=1
;------------------------------------------------------
;function ParamDemo(x, y, z : integer):integer;external
;------------------------------------------------------
   GLOBAL ParamDemo         

ParamDemo:
          PUSH BP
          MOV  BP,SP
          PUSH DS

          MOV  AX, [BP + 10] ; AX := primeiro parametro
          ADD  AX, [BP + 08] ; soma AX com segundo parametro
          ADD  AX, [BP + 06] ; soma AX com terceiro parametro

          POP DS
          POP BP
          RETF 2+2+2         ; retira os 3 parametros da pilha


{ Essa é a rotina em Turbo Pascal que chama a rotina assembly }
{$F+} { Força chamada distante }
program ParametroDemo;
{$L PROCF}
function ParamDemo(x,y,z: integer): integer; external;

var total: integer;
BEGIN
  total := ParamDemo(1,2,3);
  writeln;
  writeln('1+2+3 = ',total);
END.

                  
OBSERVAÇÃO: uma rotina distante, quando prototipada no programa principal (o executável) deve usar a diretiva {$F+} para forçar chamadas distantes. Entretanto, se for declarada na seção IMPLEMENTATION de uma UNIT, essa diretiva é opcional (a menos que você use OVERLAYS). Na seção INTERFACE da UNIT você declara o protótipo normalmente, sem usar a palavra EXTERNAL. Consulte a ajuda do Turbo Pascal para saber como usar diretivas, inclusive para definir um tamanho de pilha adequado para as suas rotinas assembly.

Anterior Próximo Índice